package com.dymedia.aibo.mvp.presenter;

import android.content.pm.PackageManager;
import android.net.ParseException;
import android.os.Build;
import android.text.TextUtils;

import com.dymedia.aibo.app.utils.Utils;
import com.dymedia.aibo.mvp.model.Entity.Channel;
import com.dymedia.aibo.mvp.model.Entity.ChannelHeader;
import com.dymedia.aibo.mvp.model.Entity.Client;
import com.dymedia.aibo.mvp.model.Entity.Group;
import com.dymedia.aibo.mvp.model.Entity.GroupHeader;
import com.dymedia.aibo.mvp.model.Entity.Video;
import com.dymedia.aibo.mvp.model.Entity.VideoHeader;
import com.dymedia.aibo.mvp.model.Repository;
import com.google.gson.JsonIOException;
import com.google.gson.JsonParseException;
import com.google.gson.stream.MalformedJsonException;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.schedulers.Schedulers;
import me.jessyan.art.di.component.AppComponent;
import me.jessyan.art.mvp.BasePresenter;
import me.jessyan.art.mvp.Message;
import me.jessyan.art.utils.DataHelper;
import me.jessyan.rxerrorhandler.core.RxErrorHandler;
import me.jessyan.rxerrorhandler.handler.ErrorHandleSubscriber;
import okhttp3.RequestBody;
import timber.log.Timber;

public class ChannelPresenter extends BasePresenter<Repository> {
    private AppComponent mAppComponent;
    private RxErrorHandler mErrorHandler;
    private List<Group> mChannelGroups = new ArrayList<>();
    private List<Group> mVideoGroups = new ArrayList<>();
    private Client mClient;
    private String mCode;
    private String mUid;
    private boolean mIsSecretMode;
    private boolean mChannelUpdate = false;
    private boolean mVideoUpdate = false;
    private boolean mGroupUpdate = false;
    public static final int MSG_ACTION_GROUP_CHANNEL = 0;
    public static final int MSG_ACTION_GROUP_VIDEO = 1;
    public static final int MSG_ACTION_VIDEO = 2;
    public static final int MSG_ACTION_CHANNEL = 3;
    public static final int MSG_ACTION_CLIENT = 4;
    public static final int MSG_ACTION_VIP = 5;
    public static final int MSG_ACTION_LIVE_PLAY = 6;
    public static final int MSG_ACTION_VIDEO_PLAY = 7;
    public static final int MSG_ACTION_LIVE_MENU_HIDE = 8;
    public static final int MSG_ACTION_DATA_ERROR = 9;

    public ChannelPresenter(AppComponent appComponent) {
        super(appComponent.repositoryManager().createRepository(Repository.class));
        this.mAppComponent = appComponent;
        this.mErrorHandler = appComponent.rxErrorHandler();
        this.mCode = Utils.getCode(mAppComponent.application());
        this.mUid = Utils.getUid();
        //this.mUid = "20A60C1AD0AC";
        //this.mUid = "AC361359918D";
        //this.mUid = "AC361359918F";
        //this.mUid = "38378B83E2AC";
    }

    public void requestChannelGroups(boolean isSecretMode, final Message msg){
        unDispose();
        this.mIsSecretMode = isSecretMode;
        if (Utils.isUsaOraoUser(mAppComponent.application()) || Utils.isUsaAisaUser(mAppComponent.application())) { //usa
            mChannelGroups.clear();
            Group group = new Group("1000", "all", "channel", false);
            mChannelGroups.add(group);
            Group group2 = new Group("1001", "other", "channel", false);
            mChannelGroups.add(group2);
            msg.what = MSG_ACTION_GROUP_CHANNEL;
            msg.handleMessageToTargetUnrecycle();
            return;
        }
        mModel.getGroups("channel", mCode, 1, mGroupUpdate).subscribeOn(Schedulers.io())
                .doOnSubscribe(disposable -> {
                        addDispose(disposable);
                    })
                .observeOn(AndroidSchedulers.mainThread())
                .doFinally(() -> {
                    Timber.d("requestChannelGroups, doFinally");})
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new ErrorHandleSubscriber<GroupHeader>(mErrorHandler) {
                    @Override
                    public void onNext(GroupHeader items) {
                        Timber.d("requestChannelGroups, onNext");
                        mChannelGroups.clear();
                        //mChannelGroups.add(new Group("id_all", "All", "channel"));
                        mChannelGroups.addAll(items.data);
                        msg.what = MSG_ACTION_GROUP_CHANNEL;
                        msg.handleMessageToTargetUnrecycle();
                    }
                    @Override
                    public void onError(@NonNull Throwable t) {
                        super.onError(t);
                    }
                });
    }

    public void requestVideoGroups(boolean isSecretMode, final Message msg){
        unDispose();
        this.mIsSecretMode = isSecretMode;
        mModel.getGroups("video", mCode, 1, mGroupUpdate).subscribeOn(Schedulers.io())
                .doOnSubscribe(disposable -> {
                        addDispose(disposable);
                    })
                .observeOn(AndroidSchedulers.mainThread())
                .doFinally(() -> {
                    Timber.d("requestVideoGroups, doFinally");})
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new ErrorHandleSubscriber<GroupHeader>(mErrorHandler) {
                    @Override
                    public void onNext(GroupHeader items) {
                        Timber.d("requestVideoGroups, onNext");
                        mVideoGroups.clear();
                        for (Group item : items.data){
                            if (mClient == null || (item.rating && !mIsSecretMode)){
                                Timber.d("requestVideoGroups, limit, name: "+item.name);
                                continue;
                            }
                            mVideoGroups.add(item);
                        }
                        msg.what = MSG_ACTION_GROUP_VIDEO;
                        msg.handleMessageToTargetUnrecycle();
                    }
                    @Override
                    public void onError(@NonNull Throwable t) {
                        super.onError(t);
                    }
                });
    }

    public void requestChannels(final Message msg) {
        unDispose();
        Observable<List<Channel>> req = getChannelsObservable();
        if (req != null) {
            req.subscribeOn(Schedulers.io())
                    .doOnSubscribe(disposable -> {
                        addDispose(disposable);})
                    .observeOn(AndroidSchedulers.mainThread())
                    .doFinally(() -> {
                        Timber.d("requestChannels, doFinally");})
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new ErrorHandleSubscriber<List<Channel>>(mErrorHandler) {
                        @Override
                        public void onNext(List<Channel> items) {
                            Timber.d("requestChannels, onNext");
                            mChannelGroups.get(0).channels.clear();
                            //解释频道中的分组
                            for (Channel item : items){
                                item.vip = true; //usr app
                                if (mClient == null || (item.vip && System.currentTimeMillis() > mClient.vip) || (item.rating && !mIsSecretMode)){
                                    Timber.d("vip limit, name: "+item.name);
                                    continue;
                                }
                                mChannelGroups.get(0).channels.add(item);
                            }
                            msg.obj = mChannelGroups;
                            msg.handleMessageToTargetUnrecycle();
                        }
                        @Override
                        public void onError(@NonNull Throwable t) {
                            if (t instanceof MalformedJsonException || t instanceof JsonParseException || t instanceof ParseException || t instanceof JSONException || t instanceof JsonIOException) {
                                msg.what = MSG_ACTION_DATA_ERROR;
                                msg.handleMessageToTargetUnrecycle();
                            } else
                                super.onError(t);
                        }
                    });
            return;
        }

        mModel.getChannels(1, 2000, mCode, 1, mChannelUpdate).subscribeOn(Schedulers.io())
                .doOnSubscribe(disposable -> {
                    addDispose(disposable);
                })
                .observeOn(AndroidSchedulers.mainThread())
                .doFinally(() -> {
                    Timber.d("requestChannels, doFinally");})
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new ErrorHandleSubscriber<ChannelHeader>(mErrorHandler) {
                    @Override
                    public void onNext(ChannelHeader items) {
                        Timber.d("requestChannels, onNext");
                        mChannelUpdate = false; //缓存开启
                        //解释频道中的分组
                        for (Channel item : items.data){
                            if (mClient == null || (item.vip && System.currentTimeMillis() > mClient.vip) || (item.rating && !mIsSecretMode)){
                                Timber.d("vip limit, name: "+item.name);
                                continue;
                            }
                            for (String g : item.group){
                                Group group = findChannelGroup(g);
                                if (group != null){
                                    group.channels.add(item);
                                }
                            }
                        }
                        msg.obj = mChannelGroups;
                        msg.handleMessageToTargetUnrecycle();
                    }
                    @Override
                    public void onError(@NonNull Throwable t) {
                        super.onError(t);
                    }
                 });
    }

    public Observable<List<Channel>> getChannelsObservable() {
        Observable<List<Channel>> req = null;
        if ("TPLDHEZP".equals(Utils.getCode(mAppComponent.application()))) {
            req = mModel.getChannels(mUid);
        } else if ("REQWOXVC".equals(Utils.getCode(mAppComponent.application()))) {
            req = mModel.getChannelsHUB(mUid);
        } else if ("YPPGLSYP".equals(Utils.getCode(mAppComponent.application()))) {
            req = mModel.getChannelsHUBTV(mUid);
        } else if ("HGOTFRKF".equals(Utils.getCode(mAppComponent.application()))) {
            req = mModel.getChannelsAsia(mUid);
        }
        return req;
    }

    public void requestVideos(final Message msg) {
        unDispose();
        mModel.getVideos(1, 2000, mCode, 1, mVideoUpdate).subscribeOn(Schedulers.io())
                .doOnSubscribe(disposable -> {
                    addDispose(disposable);
                })
                .observeOn(AndroidSchedulers.mainThread())
                .doFinally(() -> {
                    Timber.d("requestChannels, doFinally");})
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new ErrorHandleSubscriber<VideoHeader>(mErrorHandler) {
                    @Override
                    public void onNext(VideoHeader items) {
                        Timber.d("requestVideos, onNext");
                        //解释频道中的分组
                        for (Video item : items.data){
                            if (mClient == null || (item.vip && System.currentTimeMillis() > mClient.vip) || (item.rating && !mIsSecretMode)){
                                Timber.d("vip limit, name: "+item.name);
                                continue;
                            }
                            for (String g : item.group){
                                Group group = findVideoGroup(g);
                                if (group != null){
                                    group.videos.add(item);
                                }
                            }
                        }

                        msg.what = MSG_ACTION_VIDEO;
                        msg.obj = mVideoGroups;
                        msg.handleMessageToTargetUnrecycle();
                    }
                    @Override
                    public void onError(@NonNull Throwable t) {
                        super.onError(t);
                    }
                });
    }

    public void requestSetClient(final Message msg) {
        JSONObject obj = new JSONObject();
        try {
            obj.put("uid", mUid);
            obj.put("code", mCode);
            obj.put("appVersion", mAppComponent.application().getPackageManager().getPackageInfo(mAppComponent.application().getPackageName(), 0).versionName);
            obj.put("osVersion", Build.VERSION.RELEASE);
            obj.put("productManufacturer", Build.MANUFACTURER);
            obj.put("productModel", Build.MODEL);
            obj.put("product", Build.PRODUCT);
            obj.put("productSerial", Build.SERIAL);
        } catch (JSONException e) {
            e.printStackTrace();
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        RequestBody body = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"), obj.toString());
        mModel.setClient(mUid, body).subscribeOn(Schedulers.io())
                .doOnSubscribe(disposable -> {
                    addDispose(disposable);})
                .observeOn(AndroidSchedulers.mainThread())
                .doFinally(() -> {
                    Timber.d("requestSetClient, doFinally");})
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new ErrorHandleSubscriber<Client>(mErrorHandler) {
                    @Override
                    public void onNext(Client client) {
                        Timber.d("requestSetClient, onNext");
                        String md5 = DataHelper.getStringSF(mAppComponent.application(), "channelMd5");
                        if (!TextUtils.isEmpty(client.channelMd5) && !client.channelMd5.equals(md5)) {
                            DataHelper.setStringSF(mAppComponent.application(), "channelMd5", client.channelMd5);
                            mChannelUpdate = true;
                        }
                        md5 = DataHelper.getStringSF(mAppComponent.application(), "videoMd5");
                        if (client.videoMd5 == null || !TextUtils.isEmpty(client.videoMd5) && !client.videoMd5.equals(md5)) {
                            DataHelper.setStringSF(mAppComponent.application(), "videoMd5", client.videoMd5);
                            mVideoUpdate = true;
                        }
                        md5 = DataHelper.getStringSF(mAppComponent.application(), "groupMd5");
                        if (client.groupMd5 == null || !TextUtils.isEmpty(client.groupMd5) && !client.groupMd5.equals(md5)) {
                            DataHelper.setStringSF(mAppComponent.application(), "groupMd5", client.groupMd5);
                            mGroupUpdate = true;
                        }
                        mClient = client;
                        msg.obj = client;
                        msg.arg2 = mChannelUpdate ? 1 : 0;
                        msg.handleMessageToTargetUnrecycle();
                    }
                    @Override
                    public void onError(@NonNull Throwable t) {
                        super.onError(t);
                    }
                });
    }

    public void requestActiveVip(final Message msg) {
        String uid = (String)msg.obj;
        mModel.activeVip(uid, mCode, mUid).subscribeOn(Schedulers.io())
                .doOnSubscribe(disposable -> addDispose(disposable))
                .observeOn(AndroidSchedulers.mainThread())
                .doFinally(() -> {Timber.d("requestActiveVip, doFinally");})
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new ErrorHandleSubscriber<Client>(mErrorHandler) {
                    @Override
                    public void onNext(Client client) {
                        Timber.d("requestActiveVip, onNext");
                        msg.what = MSG_ACTION_VIP;//跳转
                        msg.obj = client;
                        msg.handleMessageToTargetUnrecycle();
                    }
                    @Override
                    public void onError(@NonNull Throwable t) {
                        super.onError(t);
                    }
                });
    }

    public Object[] findChannelByNumber(int number) {
        for (int i = 0; i < mChannelGroups.size(); i++) {
            for (int j = 0; mChannelGroups.get(i).channels != null && j < mChannelGroups.get(i).channels.size(); j++) {
                if (number == mChannelGroups.get(i).channels.get(j).number) {
                    return new Object[]{i, j, mChannelGroups.get(i).channels.get(j)};
                }
            }
        }
        return null;
    }

//    public Object[] findChannelByNumber(String number) {
//        for (int i = 1; i < mChannelGroups.size(); i++) {
//            for (int j = 0; mChannelGroups.get(i).channels != null && j < mChannelGroups.get(i).channels.size(); j++) {
//                if (mChannelGroups.get(i).channels.get(j).url.contains(url)) {
//                    return new Object[]{i, j, mChannelGroups.get(i).channels.get(j)};
//                }
//            }
//        }
//        return new Object[]{0, 0, mChannelGroups.get(0).channels.get(0)};
//    }

    private Group findChannelGroup(String groupId){
        for (Group group : mChannelGroups){
            if (groupId.equals(group._id)){
                return group;
            }
        }
        return null;
    }

    private Group findVideoGroup(String groupId){
        for (Group group : mVideoGroups){
            if (groupId.equals(group._id)){
                return group;
            }
        }
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        this.mErrorHandler = null;
    }
}